package ru.amse.tsyganov.jumleditor.view;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.RGB;

import ru.amse.tsyganov.jumleditor.model.State;
import ru.amse.tsyganov.jumleditor.model.Transition;

public class TransitionDraughtsman {

	public static void drawTransition(GC gc, 
			StateView<? extends State> target, 
			StateView<? extends State> source) {
		
		double targetX = target.getX();
		double targetY = target.getY();
		double targetW = target.getWidth();
		double targetH = target.getHeight();
		double targetCX = target.getCenterX();
		double targetCY = target.getCenterY();
		
		double sourceX = source.getX();
		double sourceY = source.getY();
		double sourceW = source.getWidth();
		double sourceH = source.getHeight();
		double sourceCX = source.getCenterX();
		double sourceCY = source.getCenterY();
		
		if (intersects(source, target)) {
			return;
		}
		
		int[] targetCoord = TransitionDraughtsman.getCoord(sourceX, sourceY, sourceW, sourceH, 
				sourceCX, sourceCY, targetX, targetY, 
				targetW, targetH, targetCX, targetCY);
		
		int[] sourceCoord = TransitionDraughtsman.getCoord(targetX, targetY, targetW, targetH, 
				targetCX, targetCY, sourceX, sourceY, 
				sourceW, sourceH, sourceCX, sourceCY);
		
		double a = Math.atan2(targetY - sourceY, sourceX - targetX);
		double a1 = a + Math.PI / 15;
		double a2 = a - Math.PI / 15;
		double len = 20;
		gc.drawLine(targetCoord[0], targetCoord[1], sourceCoord[0], sourceCoord[1]);
		
		gc.setBackground(new Color(null, new RGB(10, 10, 10)));
		gc.fillPolygon(new int[] {targetCoord[0], targetCoord[1], 
				(int) (targetCoord[0] + len * Math.cos(a1)), 
				(int) (targetCoord[1] - len * Math.sin(a1)),
				(int) (targetCoord[0] + len * Math.cos(a2)), 
				(int) (targetCoord[1] - len * Math.sin(a2))});
	}
	
	public static void drawTransition(GC gc, 
			TransitionView<? extends Transition> t) {
		
		if (gc == null || t == null) {
			throw new IllegalArgumentException();
		}
		
		StateView<? extends State> target = t.getTarget().getContainer();
		StateView<? extends State> source = t.getSource().getContainer();
		
		drawTransition(gc, target, source);
	}

	public static int[] getCoord(
			double sourceX, double sourceY, 
			double sourceW, double sourceH, 
			double sourceCX, double sourceCY, 
			double targetX, double targetY, 
			double targetW, double targetH, 
			double targetCX, double targetCY) {
		
		assert sourceCX >= sourceX;
		assert sourceCY >= sourceY;
		assert sourceW >= 0;
		assert sourceH >= 0;
		assert targetCX >= targetX;
		assert targetCY >= targetY;
		assert targetW >= 0;
		assert targetH >= 0;
		
		int tx;
		int ty;
		
		if ((Math.abs(sourceCX - targetCX) / Math.abs(sourceCY - targetCY)) > (sourceW / sourceH)) {
			double dy = (targetW / 2) * ((targetCY - sourceCY) / (sourceCX - targetCX));
			if (sourceCX > targetCX) {
				tx = (int) (targetX + targetW);
				ty = (int) (targetCY - dy);
			} else {
				tx = (int) targetX;
				ty = (int) (targetCY + dy);
			}
		} else {
			double dx = (targetH / 2) * ((sourceCX - targetCX) / (targetCY - sourceCY));
			if (sourceCY > targetCY) {
				tx = (int) (targetCX - dx);
				ty = (int) (targetY + targetH);
			} else {
				tx = (int) (targetCX + dx);
				ty = (int) (targetY);
			}
		}
		return new int[] {tx, ty};
	}

	private static boolean intersects(StateView stateView1, StateView stateView2) {
		
		assert stateView1 != null;
		assert stateView2 != null;
		
		return stateView1.getRectangle().intersects(stateView2.getRectangle());
	}
}
